var zrUtil = require("zrender/lib/core/util");

var graphic = require("../../util/graphic");

var Path = require("zrender/lib/graphic/Path");

/**
 * @module echarts/chart/helper/Symbol
 */
var WhiskerPath = Path.extend({
  type: 'whiskerInBox',
  shape: {},
  buildPath: function (ctx, shape) {
    for (var i in shape) {
      if (shape.hasOwnProperty(i) && i.indexOf('ends') === 0) {
        var pts = shape[i];
        ctx.moveTo(pts[0][0], pts[0][1]);
        ctx.lineTo(pts[1][0], pts[1][1]);
      }
    }
  }
});
/**
 * @constructor
 * @alias {module:echarts/chart/helper/WhiskerBox}
 * @param {module:echarts/data/List} data
 * @param {number} idx
 * @param {Function} styleUpdater
 * @param {boolean} isInit
 * @extends {module:zrender/graphic/Group}
 */

function WhiskerBox(data, idx, styleUpdater, isInit) {
  graphic.Group.call(this);
  /**
   * @type {number}
   * @readOnly
   */

  this.bodyIndex;
  /**
   * @type {number}
   * @readOnly
   */

  this.whiskerIndex;
  /**
   * @type {Function}
   */

  this.styleUpdater = styleUpdater;

  this._createContent(data, idx, isInit);

  this.updateData(data, idx, isInit);
  /**
   * Last series model.
   * @type {module:echarts/model/Series}
   */

  this._seriesModel;
}

var whiskerBoxProto = WhiskerBox.prototype;

whiskerBoxProto._createContent = function (data, idx, isInit) {
  var itemLayout = data.getItemLayout(idx);
  var constDim = itemLayout.chartLayout === 'horizontal' ? 1 : 0;
  var count = 0; // Whisker element.

  this.add(new graphic.Polygon({
    shape: {
      points: isInit ? transInit(itemLayout.bodyEnds, constDim, itemLayout) : itemLayout.bodyEnds
    },
    style: {
      strokeNoScale: true
    },
    z2: 100
  }));
  this.bodyIndex = count++; // Box element.

  var whiskerEnds = zrUtil.map(itemLayout.whiskerEnds, function (ends) {
    return isInit ? transInit(ends, constDim, itemLayout) : ends;
  });
  this.add(new WhiskerPath({
    shape: makeWhiskerEndsShape(whiskerEnds),
    style: {
      strokeNoScale: true
    },
    z2: 100
  }));
  this.whiskerIndex = count++;
};

function transInit(points, dim, itemLayout) {
  return zrUtil.map(points, function (point) {
    point = point.slice();
    point[dim] = itemLayout.initBaseline;
    return point;
  });
}

function makeWhiskerEndsShape(whiskerEnds) {
  // zr animation only support 2-dim array.
  var shape = {};
  zrUtil.each(whiskerEnds, function (ends, i) {
    shape['ends' + i] = ends;
  });
  return shape;
}
/**
 * Update symbol properties
 * @param  {module:echarts/data/List} data
 * @param  {number} idx
 */


whiskerBoxProto.updateData = function (data, idx, isInit) {
  var seriesModel = this._seriesModel = data.hostModel;
  var itemLayout = data.getItemLayout(idx);
  var updateMethod = graphic[isInit ? 'initProps' : 'updateProps']; // this.childAt(this.bodyIndex).stopAnimation(true);
  // this.childAt(this.whiskerIndex).stopAnimation(true);

  updateMethod(this.childAt(this.bodyIndex), {
    shape: {
      points: itemLayout.bodyEnds
    }
  }, seriesModel, idx);
  updateMethod(this.childAt(this.whiskerIndex), {
    shape: makeWhiskerEndsShape(itemLayout.whiskerEnds)
  }, seriesModel, idx);
  this.styleUpdater.call(null, this, data, idx);
};

zrUtil.inherits(WhiskerBox, graphic.Group);
/**
 * @constructor
 * @alias module:echarts/chart/helper/WhiskerBoxDraw
 */

function WhiskerBoxDraw(styleUpdater) {
  this.group = new graphic.Group();
  this.styleUpdater = styleUpdater;
}

var whiskerBoxDrawProto = WhiskerBoxDraw.prototype;
/**
 * Update symbols draw by new data
 * @param {module:echarts/data/List} data
 */

whiskerBoxDrawProto.updateData = function (data) {
  var group = this.group;
  var oldData = this._data;
  var styleUpdater = this.styleUpdater;
  data.diff(oldData).add(function (newIdx) {
    if (data.hasValue(newIdx)) {
      var symbolEl = new WhiskerBox(data, newIdx, styleUpdater, true);
      data.setItemGraphicEl(newIdx, symbolEl);
      group.add(symbolEl);
    }
  }).update(function (newIdx, oldIdx) {
    var symbolEl = oldData.getItemGraphicEl(oldIdx); // Empty data

    if (!data.hasValue(newIdx)) {
      group.remove(symbolEl);
      return;
    }

    if (!symbolEl) {
      symbolEl = new WhiskerBox(data, newIdx, styleUpdater);
    } else {
      symbolEl.updateData(data, newIdx);
    } // Add back


    group.add(symbolEl);
    data.setItemGraphicEl(newIdx, symbolEl);
  }).remove(function (oldIdx) {
    var el = oldData.getItemGraphicEl(oldIdx);
    el && group.remove(el);
  }).execute();
  this._data = data;
};
/**
 * Remove symbols.
 * @param {module:echarts/data/List} data
 */


whiskerBoxDrawProto.remove = function () {
  var group = this.group;
  var data = this._data;
  this._data = null;
  data && data.eachItemGraphicEl(function (el) {
    el && group.remove(el);
  });
};

var _default = WhiskerBoxDraw;
module.exports = _default;